home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / fpc / compiler / cobjects.pas < prev    next >
Pascal/Delphi Source File  |  1998-09-24  |  35KB  |  1,323 lines

  1. {
  2.     $Id: cobjects.pas,v 1.1.1.1.2.4 1998/08/31 12:19:28 peter Exp $
  3.     Copyright (c) 1993-98 by Florian Klaempfl
  4.  
  5.     This module provides some basic objects
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  ****************************************************************************
  22. }
  23.  
  24. {$ifdef tp}
  25.   {$E+,N+,D+,F+}
  26. {$endif}
  27. {$I-}
  28. {$R-}{ necessary for crc calculation }
  29.  
  30. unit cobjects;
  31.  
  32.   interface
  33.  
  34.     uses
  35.        strings
  36. {$ifndef linux}
  37.        ,dos
  38. {$else}
  39.        ,dos
  40.        ,linux
  41. {$endif}
  42.       ;
  43.  
  44.     type
  45.        pstring = ^string;
  46.  
  47.        { some help data types }
  48.        pstringitem = ^tstringitem;
  49.  
  50.        tstringitem = record
  51.           data : pstring;
  52.           next : pstringitem;
  53.        end;
  54.  
  55.        plinkedlist_item = ^tlinkedlist_item;
  56.  
  57.        tlinkedlist_item = object
  58.           next,last : plinkedlist_item;
  59.           { does nothing }
  60.           constructor init;
  61.           destructor done;virtual;
  62.        end;
  63.  
  64.        pstring_item = ^tstring_item;
  65.  
  66.        tstring_item = object(tlinkedlist_item)
  67.           str : pstring;
  68.           constructor init(const s : string);
  69.           destructor done;virtual;
  70.        end;
  71.  
  72.        plinkedlist = ^tlinkedlist;
  73.  
  74.        { this implements a double linked list }
  75.        tlinkedlist = object
  76.           first,last : plinkedlist_item;
  77.           constructor init;
  78.           destructor done;
  79.  
  80.           { disposes the items of the list }
  81.           procedure clear;
  82.  
  83.           { concats a new item at the end }
  84.           procedure concat(p : plinkedlist_item);
  85.  
  86.           { inserts a new item at the begin }
  87.           procedure insert(p : plinkedlist_item);
  88.  
  89.           { inserts another list at the begin and make this list empty }
  90.           procedure insertlist(p : plinkedlist);
  91.  
  92.           { concats another list at the end and make this list empty }
  93.           procedure concatlist(p : plinkedlist);
  94.  
  95.           { removes p from the list (p isn't disposed) }
  96.           { it's not tested if p is in the list !      }
  97.           procedure remove(p : plinkedlist_item);
  98.        end;
  99.  
  100.        { String Queue}
  101.        PStringQueue=^TStringQueue;
  102.        TStringQueue=object
  103.          first,last : PStringItem;
  104.          constructor Init;
  105.          destructor Done;
  106.          function Empty:boolean;
  107.          function Get:string;
  108.          procedure Insert(const s:string);
  109.          procedure Concat(const s:string);
  110.          procedure Clear;
  111.        end;
  112.  
  113.        { string container }
  114.        pstringcontainer = ^tstringcontainer;
  115.  
  116.        tstringcontainer = object
  117.           root,last : pstringitem;
  118.  
  119.           { if this is set to true, doubles are allowed }
  120.           { true is default                             }
  121.           doubles : boolean;
  122.           constructor init;
  123.           destructor done;
  124.  
  125.           { true is the container empty }
  126.           function empty:boolean;
  127.  
  128.  
  129.           { inserts a string }
  130.           procedure insert(const s : string);
  131.  
  132.           { gets a string }
  133.           function get : string;
  134.  
  135.           { deletes all strings }
  136.           procedure clear;
  137.        end;
  138.  
  139.        pbufferedfile = ^tbufferedfile;
  140.  
  141.        { this is implemented to allow buffered binary I/O }
  142.        tbufferedfile = object
  143.            f : file;
  144.            buf : pchar;
  145.            bufsize,buflast,bufpos : longint;
  146.  
  147.            { 0 closed, 1 input, 2 output }
  148.            iomode : byte;
  149.  
  150.            { true, if the compile should change the endian of the output }
  151.            change_endian : boolean;
  152.  
  153.            { calcules a crc for the file,                                    }
  154.            { but it's assumed, that there no seek while do_crc is true       }
  155.            do_crc : boolean;
  156.            crc : longint;
  157.  
  158.            { temporary closing feature }
  159.            tempclosed : boolean;
  160.            tempmode : byte;
  161.            temppos : longint;
  162.  
  163.            { inits a buffer with the size bufsize which is assigned to }
  164.            { the file  filename                                        }
  165.            constructor init(const filename : string;_bufsize : longint);
  166.  
  167.            { closes the file, if needed, and releases the memory }
  168.            destructor done;virtual;
  169.  
  170.            { opens the file for input, other accesses are rejected }
  171.            procedure reset;
  172.  
  173.            { opens the file for output, other accesses are rejected }
  174.            procedure rewrite;
  175.  
  176.            { reads or writes the buffer from or to disk }
  177.            procedure flush;
  178.  
  179.            { temporary closing }
  180.            procedure tempclose;
  181.            procedure tempreopen;
  182.  
  183.            { writes a string to the file }
  184.            { the string is written without a length byte }
  185.            procedure write_string(const s : string);
  186.  
  187.            { writes a zero terminated string }
  188.            procedure write_pchar(p : pchar);
  189.  
  190.            { write specific data types, takes care of }
  191.            { byte order                               }
  192.            procedure write_byte(b : byte);
  193.            procedure write_word(w : word);
  194.            procedure write_long(l : longint);
  195.            procedure write_double(d : double);
  196.  
  197.            { writes any data }
  198.            procedure write_data(var data;count : longint);
  199.  
  200.            { reads any data }
  201.            procedure read_data(var data;bytes : longint;var count : longint);
  202.  
  203.            { closes the file and releases the buffer }
  204.            procedure close;
  205.  
  206. {$ifdef MAKELIB}
  207.            { used for making tiny files for libs }
  208.            procedure changename(filename : string);
  209. {$endif MAKELIB}
  210.  
  211.            { goto the given position }
  212.            procedure seek(l : longint);
  213.  
  214.            { installes an user defined buffer      }
  215.            { and releases the old one, but be      }
  216.            { careful, if the old buffer contains   }
  217.            { data, this data is lost               }
  218.            procedure setbuf(p : pchar;s : longint);
  219.  
  220.            { reads the file time stamp of the file, }
  221.            { the file must be opened                }
  222.            function getftime : longint;
  223.  
  224.            { returns filesize }
  225.            function getsize : longint;
  226.  
  227.            { returns the path }
  228.            function getpath : string;
  229.  
  230.            { resets the crc }
  231.            procedure clear_crc;
  232.  
  233.            { returns the crc }
  234.            function getcrc : longint;
  235.        end;
  236.  
  237.     { releases the string p and assignes nil to p }
  238.     { if p=nil then freemem isn't called          }
  239.     procedure stringdispose(var p : pstring);
  240.  
  241.     { allocates mem for a copy of s, copies s to this mem and returns }
  242.     { a pointer to this mem                                           }
  243.     function stringdup(const s : string) : pstring;
  244.  
  245.     { allocates memory for s and copies s as zero terminated string
  246.       to that mem and returns a pointer to that mem }
  247.     function strpnew(const s : string) : pchar;
  248.  
  249.     { makes a char lowercase, with spanish, french and german char set }
  250.     function lowercase(c : char) : char;
  251.  
  252.     { makes zero terminated string to a pascal string }
  253.     { the data in p is modified and p is returned     }
  254.     function pchar2pstring(p : pchar) : pstring;
  255.  
  256.     { ambivalent to pchar2pstring }
  257.     function pstring2pchar(p : pstring) : pchar;
  258.  
  259.   (***********************************************************************)
  260.   (* PROCEDURE Resetfile/RewriteFile - this creates the linked list of   *)
  261.   (*  opened files - only implemented in TBufferedFile currently.        *)
  262.   (***********************************************************************)
  263.     procedure ResetFile(var f:file);
  264.     procedure RewriteFile(var f:file);
  265.   (***********************************************************************)
  266.   (* PROCEDURE CloseFile - this routine is called each time              *)
  267.   (*  a file is closed, it updates the linked list of opened files       *)
  268.   (***********************************************************************)
  269.     procedure CloseFile(var f:file);
  270.   (***********************************************************************)
  271.   (* PROCEDURE CloseAll                                                  *)
  272.   (*  This routine will close all outstanding opened files when the      *)
  273.   (*  compiler aborts - only implemented in TBufferedFile currently.     *)
  274.   (***********************************************************************)
  275.     Procedure CloseAll;
  276.  
  277.  
  278.   implementation
  279.  
  280. {****************************************************************************
  281.                                CLEAN UP ROUTINES
  282.  ****************************************************************************}
  283.  TYPE
  284.   PFileList = ^TFileList;
  285.   TFileList = record { no packed, must be correctly aligned }
  286.    Handle : longint;
  287.    Closed: boolean;
  288.    FileInfo: file;
  289.    next: pfilelist;
  290.   end;
  291.  var
  292.    fileList: pFileList;
  293.  
  294.  
  295.  
  296.  procedure ResetFile(var f:file);
  297.  var
  298.   hp: pFileList;
  299.   hp1: pfilelist;
  300.  Begin
  301.     Reset(f,1);
  302.     if InOutRes = 0 then
  303.      Begin
  304.        if FileList = nil then
  305.          Begin
  306.            new(FileList);
  307.            FileList^.Handle := filerec(f).handle;
  308.            Move(f,FileList^.FileInfo,sizeof(f));
  309.            FileList^.Closed := FALSE;
  310.            FileList^.next := nil;
  311.            exit;
  312.          end;
  313.        hp:=FileList;
  314.       { Find last list in entry }
  315.       while assigned(hp) do
  316.         Begin
  317.            if hp^.next = nil then break;
  318.            hp:=hp^.next;
  319.         end;
  320.        { Found last list in entry then add it to the list }
  321.       new(hp1);
  322.       hp^.next:=hp1;
  323.       hp1^.next:=nil;
  324.       Move(f,hp1^.FileInfo,sizeof(f));
  325.       hp1^.handle:=filerec(f).handle;
  326.       hp1^.closed:=FALSE;
  327.     end;
  328. {$IFDEF EXTDEBUG}
  329.     WriteLn('OPENED: ',filerec(f).name);
  330. {$ENDIF}
  331.  end;
  332.  
  333.  procedure RewriteFile(var f:file);
  334.  var
  335.   hp: pFileList;
  336.   hp1: pFileList;
  337.  Begin
  338.     Rewrite(f,1);
  339.     if InOutRes = 0 then
  340.      Begin
  341.        if FileList = nil then
  342.          Begin
  343.            new(FileList);
  344.            FileList^.Handle := filerec(f).handle;
  345.            Move(f,FileList^.FileInfo,sizeof(f));
  346.            FileList^.Closed := FALSE;
  347.            FileList^.next := nil;
  348.            exit;
  349.          end;
  350.        hp:=FileList;
  351.       { Find last list in entry }
  352.       while assigned(hp) do
  353.         Begin
  354.            if hp^.next = nil then break;
  355.            hp:=hp^.next;
  356.         end;
  357.        { Found last list in entry then add it to the list }
  358.       new(hp1);
  359.       hp^.next:=hp1;
  360.       hp1^.next:=nil;
  361.       Move(f,hp1^.FileInfo,sizeof(f));
  362.       hp1^.handle:=filerec(f).handle;
  363.       hp1^.closed:=FALSE;
  364.     end;
  365.  end;
  366.  
  367.  procedure CloseFile(var f:file);
  368.  var
  369.   hp: pFileList;
  370.  Begin
  371.     hp:=FileList;
  372.     while assigned(hp) do
  373.      Begin
  374.         {-------------------------------------------------------}
  375.         { This is a three step process, first is it the same    }
  376.         { file handle, if so then check if it is the same name  }
  377.         { this is possible because the file might have been     }
  378.         { closed, and the file handle assigned a new name,      }
  379.         { finally check if the file is already closed, in case  }
  380.         { we have a file opened more then once with the same    }
  381.         { handle.                                               }
  382.         { we could add more checking by rescanning if a file is }
  383.         { closed more then once.                                }
  384.         {-------------------------------------------------------}
  385.         if (hp^.handle = filerec(f).handle) and
  386.            (strcomp(filerec(hp^.FileInfo).name,filerec(f).name) = 0) and
  387.            (hp^.closed=FALSE) then
  388.          Begin
  389.            hp^.closed:=TRUE;
  390.            break;
  391.          end;
  392.         hp:=hp^.next;
  393.      end;
  394. {$IFDEF EXTDEBUG}
  395.    WriteLn('CLOSED: ',filerec(f).name);
  396. {$ENDIF EXTDEBUG}
  397.    Close(f);
  398.  end;
  399.  
  400.  Procedure CloseAll;
  401.  var
  402.   hp: pFileList;
  403.   hp1: pFileList;
  404.   f: file;
  405.  Begin
  406.     hp:=FileList;
  407.     while assigned(hp) do
  408.      Begin
  409.         if NOT (hp^.Closed) then
  410.         Begin
  411.              Move(hp^.FileInfo,f,sizeof(f));
  412. {$IFDEF EXTDEBUG}
  413.              WriteLn('FINAL CLOSE: ',filerec(f).name);
  414. {$ENDIF EXTDEBUG}
  415.              Close(f);
  416.              hp^.closed:=TRUE;
  417.         end;
  418.         hp1:=hp;
  419.         hp:=hp^.next;
  420.         dispose(hp1);
  421.      end;
  422.  end;
  423.  
  424.  
  425.     function pchar2pstring(p : pchar) : pstring;
  426.  
  427.       var
  428.          w : word;
  429.          i : longint;
  430.  
  431.       begin
  432.          w:=strlen(p);
  433.          for i:=w-1 downto 0 do
  434.            p[i+1]:=p[i];
  435.          p[0]:=chr(w);
  436.          pchar2pstring:=pstring(p);
  437.       end;
  438.  
  439.     function pstring2pchar(p : pstring) : pchar;
  440.  
  441.       var
  442.          w : word;
  443.          i : longint;
  444.  
  445.       begin
  446.          w:=ord(p^[0]);
  447.          for i:=1 to w do
  448.            p^[i-1]:=p^[i];
  449.          p^[w]:=#0;
  450.          pstring2pchar:=pchar(p);
  451.       end;
  452.  
  453.     function lowercase(c : char) : char;
  454.  
  455.        begin
  456.           case c of
  457.              #65..#90 : c := chr(ord (c) + 32);
  458.              #154 : c:=#129;  { german }
  459.              #142 : c:=#132;  { german }
  460.              #153 : c:=#148;  { german }
  461.              #144 : c:=#130;  { french }
  462.              #128 : c:=#135;  { french }
  463.              #143 : c:=#134;  { swedish/norge (?) }
  464.              #165 : c:=#164;  { spanish }
  465.              #228 : c:=#229;  { greek }
  466.              #226 : c:=#231;  { greek }
  467.              #232 : c:=#227;  { greek }
  468.           end;
  469.           lowercase := c;
  470.        end;
  471.  
  472.     function strpnew(const s : string) : pchar;
  473.       var
  474.          p : pchar;
  475.       begin
  476.          getmem(p,length(s)+1);
  477.          strpcopy(p,s);
  478.          strpnew:=p;
  479.       end;
  480.  
  481.     procedure stringdispose(var p : pstring);
  482.       begin
  483.          if assigned(p) then
  484.            freemem(p,length(p^)+1);
  485.          p:=nil;
  486.       end;
  487.  
  488.     function stringdup(const s : string) : pstring;
  489.  
  490.       var
  491.          p : pstring;
  492.  
  493.       begin
  494.          getmem(p,length(s)+1);
  495.          p^:=s;
  496.          stringdup:=p;
  497.       end;
  498.  
  499. {****************************************************************************
  500.                                   TStringQueue
  501. ****************************************************************************}
  502.  
  503. constructor TStringQueue.Init;
  504. begin
  505.   first:=nil;
  506. end;
  507.  
  508.  
  509. function TStringQueue.Empty:boolean;
  510. begin
  511.   Empty:=(first=nil);
  512. end;
  513.  
  514.  
  515. function TStringQueue.Get:string;
  516. var
  517.   hp : pstringitem;
  518. begin
  519.   if first=nil then
  520.    begin
  521.      Get:='';
  522.      exit;
  523.    end;
  524.   Get:=first^.data^;
  525.   stringdispose(first^.data);
  526.   hp:=first;
  527.   first:=first^.next;
  528.   dispose(hp);
  529. end;
  530.  
  531.  
  532. procedure TStringQueue.Insert(const s:string);
  533. var
  534.   hp : pstringitem;
  535. begin
  536.   new(hp);
  537.   hp^.next:=first;
  538.   hp^.data:=stringdup(s);
  539.   first:=hp;
  540.   if last=nil then
  541.    last:=hp;
  542. end;
  543.  
  544.  
  545. procedure TStringQueue.Concat(const s:string);
  546. var
  547.   hp : pstringitem;
  548. begin
  549.   new(hp);
  550.   hp^.next:=nil;
  551.   hp^.data:=stringdup(s);
  552.   if first=nil then
  553.    first:=hp
  554.   else
  555.    last^.next:=hp;
  556.   last:=hp;
  557. end;
  558.  
  559.  
  560. procedure TStringQueue.Clear;
  561. var
  562.   hp : pstringitem;
  563. begin
  564.   while (first<>nil) do
  565.    begin
  566.      hp:=first;
  567.      stringdispose(first^.data);
  568.      first:=first^.next;
  569.      dispose(hp);
  570.    end;
  571. end;
  572.  
  573.  
  574. destructor TStringQueue.Done;
  575. begin
  576.   Clear;
  577. end;
  578.  
  579. {****************************************************************************
  580.                            TSTRINGCONTAINER
  581.  ****************************************************************************}
  582.  
  583.     constructor tstringcontainer.init;
  584.  
  585.       begin
  586.          root:=nil;
  587.          last:=nil;
  588.          doubles:=true;
  589.       end;
  590.  
  591.     destructor tstringcontainer.done;
  592.  
  593.       begin
  594.          clear;
  595.       end;
  596.  
  597.     function tstringcontainer.empty:boolean;
  598.  
  599.  
  600.       begin
  601.         empty:=(root=nil);
  602.       end;
  603.  
  604.  
  605.     procedure tstringcontainer.insert(const s : string);
  606.  
  607.       var
  608.          hp : pstringitem;
  609.  
  610.       begin
  611.          if not(doubles) then
  612.            begin
  613.               hp:=root;
  614.               while assigned(hp) do
  615.                 begin
  616.                    if hp^.data^=s then exit;
  617.                    hp:=hp^.next;
  618.                 end;
  619.            end;
  620.          new(hp);
  621.          hp^.next:=nil;
  622.          hp^.data:=stringdup(s);
  623.          if root=nil then root:=hp
  624.            else last^.next:=hp;
  625.          last:=hp;
  626.       end;
  627.  
  628.     procedure tstringcontainer.clear;
  629.  
  630.       var
  631.          hp : pstringitem;
  632.  
  633.       begin
  634.          hp:=root;
  635.          while assigned(hp) do
  636.            begin
  637.               stringdispose(hp^.data);
  638.               root:=hp^.next;
  639.               dispose(hp);
  640.               hp:=root;
  641.            end;
  642.          last:=nil;
  643.          root:=nil;
  644.       end;
  645.  
  646.     function tstringcontainer.get : string;
  647.  
  648.       var
  649.          hp : pstringitem;
  650.  
  651.       begin
  652.          if root=nil then
  653.           get:=''
  654.          else
  655.           begin
  656.             get:=root^.data^;
  657.             hp:=root;
  658.             root:=root^.next;
  659.             stringdispose(hp^.data);
  660.             dispose(hp);
  661.           end;
  662.       end;
  663.  
  664. {****************************************************************************
  665.                             TLINKEDLIST_ITEM
  666.  ****************************************************************************}
  667.  
  668.     constructor tlinkedlist_item.init;
  669.  
  670.       begin
  671.          last:=nil;
  672.          next:=nil;
  673.       end;
  674.  
  675.     destructor tlinkedlist_item.done;
  676.  
  677.       begin
  678.       end;
  679.  
  680. {****************************************************************************
  681.                             TSTRING_ITEM
  682.  ****************************************************************************}
  683.  
  684.     constructor tstring_item.init(const s : string);
  685.  
  686.       begin
  687.          str:=stringdup(s);
  688.       end;
  689.  
  690.     destructor tstring_item.done;
  691.  
  692.       begin
  693.          stringdispose(str);
  694.          inherited done;
  695.       end;
  696.  
  697. {****************************************************************************
  698.                                TLINKEDLIST
  699.  ****************************************************************************}
  700.  
  701.     constructor tlinkedlist.init;
  702.  
  703.       begin
  704.          first:=nil;
  705.          last:=nil;
  706.       end;
  707.  
  708.     destructor tlinkedlist.done;
  709.  
  710.       begin
  711.          clear;
  712.       end;
  713.  
  714.     procedure tlinkedlist.clear;
  715.  
  716.       var
  717.          hp : plinkedlist_item;
  718.  
  719.       begin
  720.          hp:=first;
  721.          while assigned(hp) do
  722.            begin
  723.               first:=hp^.next;
  724.               dispose(hp,done);
  725.               hp:=first;
  726.            end;
  727.       end;
  728.  
  729.     procedure tlinkedlist.insertlist(p : plinkedlist);
  730.  
  731.       begin
  732.          { empty list ? }
  733.          if not(assigned(p^.first)) then
  734.            exit;
  735.  
  736.          p^.last^.next:=first;
  737.  
  738.          { we have a double linked list }
  739.          if assigned(first) then
  740.            first^.last:=p^.last;
  741.  
  742.          first:=p^.first;
  743.  
  744.          if not(assigned(last)) then
  745.            last:=p^.last;
  746.  
  747.          { p becomes empty }
  748.          p^.first:=nil;
  749.          p^.last:=nil;
  750.       end;
  751.  
  752.     procedure tlinkedlist.concat(p : plinkedlist_item);
  753.  
  754.       begin
  755.          p^.last:=nil;
  756.          p^.next:=nil;
  757.          if not(assigned(first)) then
  758.            first:=p
  759.            else
  760.              begin
  761.                 last^.next:=p;
  762.                 p^.last:=last;
  763.              end;
  764.          last:=p;
  765.       end;
  766.  
  767.     procedure tlinkedlist.insert(p : plinkedlist_item);
  768.  
  769.       begin
  770.          p^.last:=nil;
  771.          p^.next:=nil;
  772.          if not(assigned(first)) then
  773.            last:=p
  774.          else
  775.            begin
  776.               first^.last:=p;
  777.               p^.next:=first;
  778.               first:=p;
  779.            end;
  780.          first:=p;
  781.       end;
  782.  
  783.     procedure tlinkedlist.remove(p : plinkedlist_item);
  784.  
  785.       begin
  786.          if not(assigned(p)) then
  787.            exit;
  788.          if (first=p) and (last=p) then
  789.            begin
  790.               first:=nil;
  791.               last:=nil;
  792.            end
  793.          else if first=p then
  794.            begin
  795.               first:=p^.next;
  796.               if assigned(first) then
  797.                 first^.last:=nil;
  798.            end
  799.          else if last=p then
  800.            begin
  801.               last:=last^.last;
  802.               if assigned(last) then
  803.                 last^.next:=nil;
  804.            end
  805.          else
  806.            begin
  807.               p^.last^.next:=p^.next;
  808.               p^.next^.last:=p^.last;
  809.            end;
  810.          p^.next:=nil;
  811.          p^.last:=nil;
  812.       end;
  813.  
  814.     procedure tlinkedlist.concatlist(p : plinkedlist);
  815.  
  816.      begin
  817.          if not(assigned(p^.first)) then
  818.            exit;
  819.  
  820.          if not(assigned(first)) then
  821.            first:=p^.first
  822.            else
  823.              begin
  824.                 last^.next:=p^.first;
  825.                 p^.first^.last:=last;
  826.              end;
  827.  
  828.          last:=p^.last;
  829.  
  830.          { make p empty }
  831.          p^.last:=nil;
  832.          p^.first:=nil;
  833.       end;
  834.  
  835. {****************************************************************************
  836.                                TBUFFEREDFILE
  837.  ****************************************************************************}
  838.  
  839.     Const
  840.        crcseed = $ffffffff;
  841.  
  842.        crctable : array[0..255] of longint = (
  843.           $00000000,$77073096,$ee0e612c,$990951ba,$076dc419,$706af48f,
  844.           $e963a535,$9e6495a3,$0edb8832,$79dcb8a4,$e0d5e91e,$97d2d988,
  845.           $09b64c2b,$7eb17cbd,$e7b82d07,$90bf1d91,$1db71064,$6ab020f2,
  846.           $f3b97148,$84be41de,$1adad47d,$6ddde4eb,$f4d4b551,$83d385c7,
  847.           $136c9856,$646ba8c0,$fd62f97a,$8a65c9ec,$14015c4f,$63066cd9,
  848.           $fa0f3d63,$8d080df5,$3b6e20c8,$4c69105e,$d56041e4,$a2677172,
  849.           $3c03e4d1,$4b04d447,$d20d85fd,$a50ab56b,$35b5a8fa,$42b2986c,
  850.           $dbbbc9d6,$acbcf940,$32d86ce3,$45df5c75,$dcd60dcf,$abd13d59,
  851.           $26d930ac,$51de003a,$c8d75180,$bfd06116,$21b4f4b5,$56b3c423,
  852.           $cfba9599,$b8bda50f,$2802b89e,$5f058808,$c60cd9b2,$b10be924,
  853.           $2f6f7c87,$58684c11,$c1611dab,$b6662d3d,$76dc4190,$01db7106,
  854.           $98d220bc,$efd5102a,$71b18589,$06b6b51f,$9fbfe4a5,$e8b8d433,
  855.           $7807c9a2,$0f00f934,$9609a88e,$e10e9818,$7f6a0dbb,$086d3d2d,
  856.           $91646c97,$e6635c01,$6b6b51f4,$1c6c6162,$856530d8,$f262004e,
  857.           $6c0695ed,$1b01a57b,$8208f4c1,$f50fc457,$65b0d9c6,$12b7e950,
  858.           $8bbeb8ea,$fcb9887c,$62dd1ddf,$15da2d49,$8cd37cf3,$fbd44c65,
  859.           $4db26158,$3ab551ce,$a3bc0074,$d4bb30e2,$4adfa541,$3dd895d7,
  860.           $a4d1c46d,$d3d6f4fb,$4369e96a,$346ed9fc,$ad678846,$da60b8d0,
  861.           $44042d73,$33031de5,$aa0a4c5f,$dd0d7cc9,$5005713c,$270241aa,
  862.           $be0b1010,$c90c2086,$5768b525,$206f85b3,$b966d409,$ce61e49f,
  863.           $5edef90e,$29d9c998,$b0d09822,$c7d7a8b4,$59b33d17,$2eb40d81,
  864.           $b7bd5c3b,$c0ba6cad,$edb88320,$9abfb3b6,$03b6e20c,$74b1d29a,
  865.           $ead54739,$9dd277af,$04db2615,$73dc1683,$e3630b12,$94643b84,
  866.           $0d6d6a3e,$7a6a5aa8,$e40ecf0b,$9309ff9d,$0a00ae27,$7d079eb1,
  867.           $f00f9344,$8708a3d2,$1e01f268,$6906c2fe,$f762575d,$806567cb,
  868.           $196c3671,$6e6b06e7,$fed41b76,$89d32be0,$10da7a5a,$67dd4acc,
  869.           $f9b9df6f,$8ebeeff9,$17b7be43,$60b08ed5,$d6d6a3e8,$a1d1937e,
  870.           $38d8c2c4,$4fdff252,$d1bb67f1,$a6bc5767,$3fb506dd,$48b2364b,
  871.           $d80d2bda,$af0a1b4c,$36034af6,$41047a60,$df60efc3,$a867df55,
  872.           $316e8eef,$4669be79,$cb61b38c,$bc66831a,$256fd2a0,$5268e236,
  873.           $cc0c7795,$bb0b4703,$220216b9,$5505262f,$c5ba3bbe,$b2bd0b28,
  874.           $2bb45a92,$5cb36a04,$c2d7ffa7,$b5d0cf31,$2cd99e8b,$5bdeae1d,
  875.           $9b64c2b0,$ec63f226,$756aa39c,$026d930a,$9c0906a9,$eb0e363f,
  876.           $72076785,$05005713,$95bf4a82,$e2b87a14,$7bb12bae,$0cb61b38,
  877.           $92d28e9b,$e5d5be0d,$7cdcefb7,$0bdbdf21,$86d3d2d4,$f1d4e242,
  878.           $68ddb3f8,$1fda836e,$81be16cd,$f6b9265b,$6fb077e1,$18b74777,
  879.           $88085ae6,$ff0f6a70,$66063bca,$11010b5c,$8f659eff,$f862ae69,
  880.           $616bffd3,$166ccf45,$a00ae278,$d70dd2ee,$4e048354,$3903b3c2,
  881.           $a7672661,$d06016f7,$4969474d,$3e6e77db,$aed16a4a,$d9d65adc,
  882.           $40df0b66,$37d83bf0,$a9bcae53,$debb9ec5,$47b2cf7f,$30b5ffe9,
  883.           $bdbdf21c,$cabac28a,$53b39330,$24b4a3a6,$bad03605,$cdd70693,
  884.           $54de5729,$23d967bf,$b3667a2e,$c4614ab8,$5d681b02,$2a6f2b94,
  885.           $b40bbe37,$c30c8ea1,$5a05df1b,$2d02ef8d);
  886.  
  887.     constructor tbufferedfile.init(const filename : string;_bufsize : longint);
  888.  
  889.       begin
  890.          assign(f,filename);
  891.          bufsize:=_bufsize;
  892.          bufpos:=0;
  893.          buflast:=0;
  894.          do_crc:=false;
  895.          iomode:=0;
  896.          change_endian:=false;
  897.          clear_crc;
  898.       end;
  899.  
  900.     destructor tbufferedfile.done;
  901.  
  902.       begin
  903.          close;
  904.       end;
  905.  
  906.     procedure tbufferedfile.clear_crc;
  907.  
  908.       begin
  909.          crc:=crcseed;
  910.       end;
  911.  
  912.     procedure tbufferedfile.setbuf(p : pchar;s : longint);
  913.  
  914.       begin
  915.          flush;
  916.          freemem(buf,bufsize);
  917.          bufsize:=s;
  918.          buf:=p;
  919.       end;
  920.  
  921.     procedure tbufferedfile.reset;
  922.  
  923.       var
  924.          ofm : byte;
  925.       begin
  926.          ofm:=filemode;
  927.          iomode:=1;
  928.          getmem(buf,bufsize);
  929.          filemode:=0;
  930.          resetfile(f);
  931.          filemode:=ofm;
  932.       end;
  933.  
  934.     procedure tbufferedfile.rewrite;
  935.  
  936.       begin
  937.          iomode:=2;
  938.          getmem(buf,bufsize);
  939.          system.rewrite(f,1);
  940.       end;
  941.  
  942.     procedure tbufferedfile.flush;
  943.  
  944.       var
  945. {$ifdef FPC}
  946.          count : longint;
  947. {$else}
  948.          count : integer;
  949. {$endif}
  950.  
  951.       begin
  952.          if iomode=2 then
  953.            begin
  954.               if bufpos=0 then
  955.                 exit;
  956.               blockwrite(f,buf^,bufpos)
  957.            end
  958.          else if iomode=1 then
  959.             if buflast=bufpos then
  960.               begin
  961.                  blockread(f,buf^,bufsize,count);
  962.                  buflast:=count;
  963.               end;
  964.          bufpos:=0;
  965.       end;
  966.  
  967.  
  968.     procedure tbufferedfile.tempclose;
  969.  
  970.       begin
  971.         if iomode<>0 then
  972.          begin
  973.            temppos:=system.filepos(f);
  974.            tempmode:=iomode;
  975.            tempclosed:=true;
  976.            closeFile(f);
  977.            iomode:=0;
  978.          end
  979.         else
  980.          tempclosed:=false;
  981.       end;
  982.  
  983.     procedure tbufferedfile.tempreopen;
  984.  
  985.       var
  986.          ofm : byte;
  987.  
  988.       begin
  989.          if tempclosed then
  990.            begin
  991.               case tempmode of
  992.                1 : begin
  993.                      ofm:=filemode;
  994.                      iomode:=1;
  995.                      filemode:=0;
  996.                      resetfile(f);
  997.                      filemode:=ofm;
  998.                    end;
  999.                2 : begin
  1000.                      iomode:=2;
  1001.                      rewritefile(f);
  1002.                    end;
  1003.               end;
  1004.               system.seek(f,temppos);
  1005.               tempclosed:=false;
  1006.            end;
  1007.       end;
  1008.  
  1009.     function tbufferedfile.getftime : longint;
  1010.  
  1011.       var
  1012.          l : longint;
  1013. {$ifdef linux}
  1014.          Info : Stat;
  1015. {$endif}
  1016.       begin
  1017. {$ifndef linux}
  1018.          { this only works if the file is open !! }
  1019.          dos.getftime(f,l);
  1020. {$else}
  1021.          Fstat(f,Info);
  1022.          l:=info.mtime;
  1023. {$endif}
  1024.          getftime:=l;
  1025.       end;
  1026.  
  1027.     function tbufferedfile.getsize : longint;
  1028.  
  1029.       begin
  1030.         getsize:=filesize(f);
  1031.       end;
  1032.  
  1033.     procedure tbufferedfile.seek(l : longint);
  1034.  
  1035.       begin
  1036.          if iomode=2 then
  1037.            begin
  1038.               flush;
  1039.               system.seek(f,l);
  1040.            end
  1041.          else if iomode=1 then
  1042.            begin
  1043.               { forces a reload }
  1044.               bufpos:=buflast;
  1045.               system.seek(f,l);
  1046.               flush;
  1047.            end;
  1048.       end;
  1049.  
  1050.     type
  1051. {$ifdef tp}
  1052.        bytearray1 = array [1..65535] of byte;
  1053. {$else}
  1054.        bytearray1 = array [1..10000000] of byte;
  1055. {$endif}
  1056.  
  1057.     procedure tbufferedfile.read_data(var data;bytes : longint;var count : longint);
  1058.  
  1059.       var
  1060.          p : pchar;
  1061.          c,i : longint;
  1062.  
  1063.       begin
  1064.          p:=pchar(@data);
  1065.          count:=0;
  1066.          while bytes-count>0 do
  1067.            begin
  1068.               if bytes-count>buflast-bufpos then
  1069.                 begin
  1070.                    move((buf+bufpos)^,(p+count)^,buflast-bufpos);
  1071.                    inc(count,buflast-bufpos);
  1072.                    bufpos:=buflast;
  1073.                    flush;
  1074.                    { can't we read anything ? }
  1075.                    if bufpos=buflast then
  1076.                      break;
  1077.                 end
  1078.               else
  1079.                 begin
  1080.                    move((buf+bufpos)^,(p+count)^,bytes-count);
  1081.                    inc(bufpos,bytes-count);
  1082.                    count:=bytes;
  1083.                    break;
  1084.                 end;
  1085.            end;
  1086.          if do_crc then
  1087.            begin
  1088.               c:=crc;
  1089.               for i:=1 to bytes do
  1090.               c:=(c shr 8) xor crctable[byte(c) xor (bytearray1(data)[i])];
  1091.               crc:=c;
  1092.            end;
  1093.       end;
  1094.  
  1095.     procedure tbufferedfile.write_data(var data;count : longint);
  1096.  
  1097.       var
  1098.          c,i : longint;
  1099.  
  1100.       begin
  1101.          if bufpos+count>bufsize then
  1102.            flush;
  1103.          move(data,(buf+bufpos)^,count);
  1104.          inc(bufpos,count);
  1105.          if do_crc then
  1106.            begin
  1107.               c:=crc;
  1108.               for i:=1 to count do
  1109.                 c:=(c shr 8) xor crctable[byte(c) xor (bytearray1(data)[i])];
  1110.               crc:=c;
  1111.            end;
  1112.       end;
  1113.  
  1114.     function tbufferedfile.getcrc : longint;
  1115.  
  1116.       begin
  1117.          getcrc:=crc xor crcseed;
  1118.       end;
  1119.  
  1120.     procedure tbufferedfile.write_string(const s : string);
  1121.  
  1122.       begin
  1123.         if bufpos+length(s)>bufsize then
  1124.           flush;
  1125.         move(s[1],(buf+bufpos)^,length(s));
  1126.         inc(bufpos,length(s));
  1127.       end;
  1128.  
  1129.     procedure tbufferedfile.write_pchar(p : pchar);
  1130.  
  1131.       var
  1132.          l : longint;
  1133.  
  1134.       begin
  1135.         l:=strlen(p);
  1136.         if l>=bufsize then
  1137.           runerror(222);
  1138.         if bufpos+l>bufsize then
  1139.           flush;
  1140.         move(p^,(buf+bufpos)^,l);
  1141.         inc(bufpos,l);
  1142.       end;
  1143.  
  1144.     procedure tbufferedfile.write_byte(b : byte);
  1145.  
  1146.       begin
  1147.          write_data(b,sizeof(byte));
  1148.       end;
  1149.  
  1150.     procedure tbufferedfile.write_long(l : longint);
  1151.  
  1152.       var
  1153.          w1,w2 : word;
  1154.  
  1155.       begin
  1156.          if change_endian then
  1157.            begin
  1158.               w1:=l and $ffff;
  1159.               w2:=l shr 16;
  1160.               l:=swap(w2)+(longint(swap(w1)) shl 16);
  1161.               write_data(l,sizeof(longint))
  1162.            end
  1163.          else
  1164.            write_data(l,sizeof(longint))
  1165.       end;
  1166.  
  1167.     procedure tbufferedfile.write_word(w : word);
  1168.  
  1169.       begin
  1170.          if change_endian then
  1171.            begin
  1172.               w:=swap(w);
  1173.               write_data(w,sizeof(word))
  1174.            end
  1175.          else
  1176.            write_data(w,sizeof(word));
  1177.       end;
  1178.  
  1179.     procedure tbufferedfile.write_double(d : double);
  1180.  
  1181.       begin
  1182.          write_data(d,sizeof(double));
  1183.       end;
  1184.  
  1185.     function tbufferedfile.getpath : string;
  1186.  
  1187.       begin
  1188. {$ifdef dummy}
  1189.          getpath:=strpas(filerec(f).name);
  1190. {$endif}
  1191.          getpath:='';
  1192.       end;
  1193.  
  1194.     procedure tbufferedfile.close;
  1195.  
  1196.       begin
  1197.          if iomode<>0 then
  1198.            begin
  1199.               flush;
  1200.               closeFile(f);
  1201.               freemem(buf,bufsize);
  1202.               iomode:=0;
  1203.            end;
  1204.       end;
  1205. {$ifdef MAKELIB}
  1206.     procedure tbufferedfile.changename(filename : string);
  1207.  
  1208.       begin
  1209.          close;
  1210.          assign(f,filename);
  1211.       end;
  1212. {$endif MAKELIB}
  1213. end.
  1214. {
  1215.   $Log: cobjects.pas,v $
  1216.   Revision 1.1.1.1.2.4  1998/08/31 12:19:28  peter
  1217.     * linux fixes
  1218.  
  1219.   Revision 1.1.1.1.2.3  1998/08/18 13:38:40  carl
  1220.     * implemented error recovery for files
  1221.  
  1222.   Revision 1.1.1.1.2.2  1998/08/05 10:33:50  pierre
  1223.     * added tempclose and temp reopen
  1224.       to be able to compile lots of dependent units
  1225.  
  1226.   Revision 1.1.1.1.2.1  1998/04/07 11:26:10  peter
  1227.     +  filemode fix
  1228.  
  1229.   Revision 1.2  1998/04/07 11:09:04  peter
  1230.     + filemode is set correct in tbufferedfile.reset
  1231.  
  1232.   Revision 1.1.1.1  1998/03/25 11:18:15  root
  1233.   * Restored version
  1234.  
  1235.   Revision 1.15  1998/03/10 16:27:38  pierre
  1236.     * better line info in stabs debug
  1237.     * symtabletype and lexlevel separated into two fields of tsymtable
  1238.     + ifdef MAKELIB for direct library output, not complete
  1239.     + ifdef CHAINPROCSYMS for overloaded seach across units, not fully
  1240.       working
  1241.     + ifdef TESTFUNCRET for setting func result in underfunction, not
  1242.       working
  1243.  
  1244.   Revision 1.14  1998/03/10 01:17:18  peter
  1245.     * all files have the same header
  1246.     * messages are fully implemented, EXTDEBUG uses Comment()
  1247.     + AG... files for the Assembler generation
  1248.  
  1249.   Revision 1.13  1998/03/04 17:33:42  michael
  1250.   + Changed ifdef FPK to ifdef FPC
  1251.  
  1252.   Revision 1.12  1998/03/02 01:48:31  peter
  1253.     * renamed target_DOS to target_GO32V1
  1254.     + new verbose system, merged old errors and verbose units into one new
  1255.       verbose.pas, so errors.pas is obsolete
  1256.  
  1257.   Revision 1.11  1998/02/28 00:20:22  florian
  1258.     * more changes to get import libs for Win32 working
  1259.  
  1260.   Revision 1.10  1998/02/24 14:20:50  peter
  1261.     + tstringcontainer.empty
  1262.     * ld -T option restored for linux
  1263.     * libraries are placed before the objectfiles in a .PPU file
  1264.     * removed 'uses link' from files.pas
  1265.  
  1266.   Revision 1.9  1998/02/18 13:48:17  michael
  1267.   + Implemented an OS independent AsmRes object.
  1268.  
  1269.   Revision 1.8  1998/02/17 21:20:45  peter
  1270.     + Script unit
  1271.     + __EXIT is called again to exit a program
  1272.     - target_info.link/assembler calls
  1273.     * linking works again for dos
  1274.     * optimized a few filehandling functions
  1275.     * fixed stabs generation for procedures
  1276.  
  1277.   Revision 1.7  1998/02/13 10:34:55  daniel
  1278.   * Made Motorola version compilable.
  1279.   * Fixed optimizer
  1280.  
  1281.   Revision 1.6  1998/02/12 11:50:01  daniel
  1282.   Yes! Finally! After three retries, my patch!
  1283.  
  1284.   Changes:
  1285.  
  1286.   Complete rewrite of psub.pas.
  1287.   Added support for DLL's.
  1288.   Compiler requires less memory.
  1289.   Platform units for each platform.
  1290.  
  1291.   Revision 1.5  1998/02/06 23:08:32  florian
  1292.     + endian to targetinfo and sourceinfo added
  1293.     + endian independed writing of ppu file (reading missed), a PPU file
  1294.       is written with the target endian
  1295.  
  1296.   Revision 1.4  1998/01/13 17:11:34  michael
  1297.   * Changed getftime method to work faster under linux.
  1298.  
  1299.   Revision 1.3  1997/12/05 13:45:34  daniel
  1300.   - Removed overlay init. This is done by PPOVIN.PAS.
  1301.  
  1302.   Revision 1.2  1997/11/28 18:14:28  pierre
  1303.    working version with several bug fixes
  1304.  
  1305.   Revision 1.1.1.1  1997/11/27 08:32:55  michael
  1306.   FPC Compiler CVS start
  1307.  
  1308.  Pre-CVS log:
  1309.  
  1310.  History:
  1311.       30th september 1996:
  1312.          + english comments (FK)
  1313.          + _2pchar renamed to pstring2pchar (FK)
  1314.          + _2pstring renamed to pchar2pstring (FK)
  1315.       15th october 1996:
  1316.          + tstringcontainer is compilable (FK)
  1317.          + full compilable (FK)
  1318.        4th january 1996:
  1319.          + tstring_item added (FK)
  1320.       19th november 1997:
  1321.          + call of overlay init (FK)
  1322. }
  1323.